﻿using System;
using System.Collections.Generic;
using System.Drawing; 

namespace ICSharpCode.WinFormsUI.Controls.Chart3D
{
    public class GraphicShapes3D
    {
        private double xmax, ymax, zmax = 0;
        private double xmin, ymin, zmin = 0;

        private Shape3D SelectedShape = null;
        private Point3D SelectedPoint3d = null;     

        private ViewPort viewPort = null;
        private Dictionary<string, Shape3D> shapes3d = new Dictionary<string, Shape3D>();

        private Font font = new Font("宋体", 9.0f);
        public Font Font
        {
            get { return font; }
            set { font = value; }
        }

        public GraphicShapes3D()
        {

        }

        public GraphicShapes3D(ViewPort viewPort)
            : this()
        {
            this.viewPort = viewPort;             
        }

        internal void Draw(Graphics g)
        {
            DrawShapes(g);
            DrawSelectedPoint(g);
        }

        void DrawShapes(Graphics g)
        {
            foreach (var shape in shapes3d.Values)
            {
                shape.Draw(g);
            }
        }

        void DrawSelectedPoint(Graphics g)
        {
            if (SelectedShape != null && SelectedPoint3d != null)
            {
                var d = SelectedShape.GetType();
                if (SelectedShape.GetType().Equals(typeof(SmoothCurve3D)))
                {
                    float _selectedDashStyleSize = SelectedShape.DashStyleSize + 2;
                    Point2D pt2d = viewPort.Camera.GetProjection(Convert.ToVertex(viewPort.Coordinate, SelectedPoint3d));
                    g.FillEllipse(new SolidBrush(SelectedShape.SelectedDashStyleColor), pt2d.X - _selectedDashStyleSize, pt2d.Y - _selectedDashStyleSize, 2 * _selectedDashStyleSize, 2 * _selectedDashStyleSize);
                    string ToShowValues = string.Format(SelectedShape.CursorValueFormat.Replace("{name}", SelectedShape.Name), SelectedPoint3d.X.ToString("F2"), SelectedPoint3d.Y.ToString("F2"), SelectedPoint3d.Z.ToString("F2"));
                    SizeF labelSize = g.MeasureString(ToShowValues, viewPort.Chart.Font);
                    g.DrawString(ToShowValues, font, Brushes.Blue, viewPort.Chart.Width - labelSize.Width - 6, 10);
                }                
            }
        }

        public SmoothCurve3D AddSmoothCurve3D(string name, Shape3D shape)
        {
            shape = new SmoothCurve3D(viewPort.Chart, viewPort.Camera, viewPort.Coordinate)
            {
                Name = name,
                CursorValueFormat=((NChart3DControl)viewPort.Chart).CursorValueFormat,
                LineColor = shape.LineColor,
                LineWidth = shape.LineWidth
            };
            if (!shapes3d.ContainsKey(name))
                shapes3d.Add(name, shape);
            if (shape.invalidateable)
                viewPort.Chart.Invalidate();
            shape.Event = new delegateEvent(shape_Event);
            return (SmoothCurve3D)shape;
        }

        public ColumnBar3D AddColumnBar3D(string name, Shape3D shape)
        {
            shape = new ColumnBar3D(viewPort.Chart, viewPort.Camera, viewPort.Coordinate)
            {
                Name = name,
                CursorValueFormat = ((NChart3DControl)viewPort.Chart).CursorValueFormat,
                LineColor = shape.LineColor,
                LineWidth = shape.LineWidth
            };
            if (!shapes3d.ContainsKey(name))
                shapes3d.Add(name, shape);
            if (shape.invalidateable)
                viewPort.Chart.Invalidate();
            shape.Event = new delegateEvent(shape_Event);
            return (ColumnBar3D)shape;
        }

        protected void shape_Event(Point3D[] points)
        {
            if (points != null)
            {
                foreach (Point3D pt3d in points)
                {
                    if (pt3d.X > xmax)
                    {
                        xmax = pt3d.X;
                    }
                    if (pt3d.Y > ymax)
                    {
                        ymax = pt3d.Y;
                    }
                    if (pt3d.Z > zmax)
                    {
                        zmax = pt3d.Z;
                    }

                    if (pt3d.X < xmin)
                    {
                        xmin = pt3d.X;
                    }
                    if (pt3d.Y < ymin)
                    {
                        ymin = pt3d.Y;
                    }
                    if (pt3d.Z < zmin)
                    {
                        zmin = pt3d.Z;
                    }
                }

                viewPort.Coordinate.Xaxis.Min = xmin;
                viewPort.Coordinate.Yaxis.Min = ymin;
                viewPort.Coordinate.Zaxis.Min = zmin;

                viewPort.Coordinate.Xaxis.Max = xmax;
                viewPort.Coordinate.Yaxis.Max = ymax;
                viewPort.Coordinate.Zaxis.Max = zmax;
            }           

        }

        public Point3D FindNestPoint(Point point, out Shape3D shape)
        {
            Point3D result = null; shape = null;
            foreach (var shape3d in shapes3d.Values)
            {
                if (shape3d.FindNestPoint(point, out result))
                {
                    shape = shape3d;
                    break;
                }
            }
            return result;
        }

        internal void SetCursorPoint3d(Shape3D shape, Point3D pt3d)
        {
            SelectedPoint3d = pt3d;
            SelectedShape = shape;
            if (shape != null)
            {
                shape.SelectedPoint3d = SelectedPoint3d;
                if (viewPort.Chart.ShapeClick != null && viewPort.Chart.ShapeClick.eventHandler != null)
                {
                    if (viewPort.Chart.Cursor != System.Windows.Forms.Cursors.Hand)
                        viewPort.Chart.Cursor = System.Windows.Forms.Cursors.Hand;
                }
            }
            else if (viewPort.Chart.ShapeClick != null && viewPort.Chart.ShapeClick.eventHandler != null)
            {
                if (viewPort.Chart.Cursor != System.Windows.Forms.Cursors.Default)
                    viewPort.Chart.Cursor = System.Windows.Forms.Cursors.Default;
            }
            viewPort.Chart.Invalidate();
        }

    }
}
